/*
*******************************************************************************
** Copyright (C), 2014-2020, TONLY AV R&D CENTER SOFTWARE DEVELOPMENT DEPARTMENT
** FileName: 
** <author>:             
** Date:
** Description:
**
** Others:
** Function List:
**   1.
** History:
**  <Author>    <date>    <content>    <version>
*******************************************************************************
*/
//*****************************************************************************
// File Include
//*****************************************************************************
#include "cdn_key.h"
#include "app_log.h"
#include <string.h>
#include "input_ring_buffer.h"
#include "sl_status.h"
#include "sl_btmesh_api.h"
#include "cdn_nvm3.h"
#include "app.h"
#include "sl_btmesh_factory_reset.h"
#include "cdn_light.h"
#include "cdn_adv.h"

//*****************************************************************************
// Local Defines
//*****************************************************************************
#define RESET_TOUCH_INTERVAL 750 //15s



//*****************************************************************************
// Local Data
//*****************************************************************************
static KeyActionInfo mKeyInfo = {0};
static KeyInfo mKeyState = {1,0};

static uint8_t ResetCnt = 0;
static uint8_t ResetNextCnt = 0;
static uint8_t ResetTimerStartFlag = 0;

//*****************************************************************************
// Global Data
//*****************************************************************************

//*****************************************************************************
// API Functions
//*****************************************************************************
//获取某个按键的所有信息
static void GetKeyInfo(uint8_t Keyid,KeyInfo *Buf)
{
  if(!Buf || Keyid < 1 || Keyid > KEY_NUM_CNT)
    return;

  memcpy(Buf,&(mKeyState),sizeof(mKeyState)); //复制按键信息
}


//获取按键键值
static uint8_t get_key_value(void)
{
  uint8_t GpioKey = KEY_ID_NULL;

  if(!GPIO_PinInGet(CDN_KEY1_PORT, CDN_KEY1_PIN))  //读取IO值
  {
    GpioKey = KEY_ID_1;
  }

  return GpioKey;
}


//按键扫描
void key_scan(void)
{
  uint8_t KeyTempID = KEY_ID_NULL;
  static uint16_t KeyCurrentTime = 0;

  if(KeyCurrentTime) // 该变量值为0的时候停止计时
  {
    KeyCurrentTime++;
  }

  KeyTempID = get_key_value();

  switch(mKeyInfo.state)
  {
    case KEY_STATE_IDLE:
      if(KEY_ID_NULL != KeyTempID)
      {
        mKeyInfo.key.id   = KeyTempID;      //记录当前按下的按键ID
        mKeyInfo.state    = KEY_STATE_PRESS ; //有按键按下
        mKeyInfo.key.down = 0;
      }
      break;

    case KEY_STATE_PRESS:
      if(KeyTempID == mKeyInfo.key.id)
      {
        if(++(mKeyInfo.key.down) == DEBOUNCE_COUNT) //一个按键扫描周期消抖
        {
          if(mKeyInfo.key.id != mKeyInfo.preId)
          {
            KeyCurrentTime = 1;     //当按下新键时重新启动计时
            mKeyInfo.repeatCnt = 0;   //按下新键，双击计数重新计算
          }
          else
          {
            if(KeyCurrentTime == 0)
            {
              KeyCurrentTime = 1; //开始计时
            }
          }

          mKeyInfo.result = KEY_RESULT_CLICK; //单击生效
          mKeyInfo.state = KEY_STATE_HOLD;
        }
      }
      else
      {
        mKeyInfo.state = KEY_STATE_IDLE;
      }
      break;

    case KEY_STATE_HOLD:
      if(KeyTempID == mKeyInfo.key.id)
      {
        (mKeyInfo.key.down)++;

        if(KeyCurrentTime > KEY_REPEAT_CLICK_INTERVAL)  //双击间隔时间超过设定值，认为双击无效
        {
          KeyCurrentTime = 0; //停止计时
          mKeyInfo.repeatCnt = 0;
        }

        if(mKeyInfo.key.down >= 65000)
        {
          mKeyInfo.key.down = 0;
        }

        if(mKeyInfo.key.down <= LONG_COUNT_1S * 20) //长按时间最长不能超过20S
        {
					if(mKeyInfo.key.down >= LONG_DOWN_TIME_1S) //长按1s
					{
						mKeyInfo.result = KEY_RESULT_LONG_DOWN;
					}

					if(mKeyInfo.key.down >= LONG_DOWN_TIME_4S) //长按5s
					{
						mKeyInfo.result = KEY_RESULT_LONG_DOWN_5S;
					}
				
          if(mKeyInfo.key.down >= LONG_LONG_DOWN_TIME_10S) //超长按10S
          {
            mKeyInfo.result = KEY_RESULT_LONG_LONG_DOWN;
          }
        }
      }
      else
      {
        mKeyInfo.key.up = 0;
        mKeyInfo.state = KEY_STATE_RELEASE;
      }
      break;

    case KEY_STATE_RELEASE:
      if(KeyTempID != mKeyInfo.key.id)  //检查按下的键是否被释放
      {
        if(++(mKeyInfo.key.up) == DEBOUNCE_COUNT)
        {
          if(KeyCurrentTime > 0)
          {
            mKeyInfo.repeatCnt++; //计时器未停止，双击间隔时间计数
          }

          if(mKeyInfo.repeatCnt > 1)
          {
            mKeyInfo.result = KEY_RESULT_REPEAT_CLICK;
            KeyCurrentTime = 0; //停止计时
            mKeyInfo.repeatCnt = 0;
            mKeyInfo.click_time = 0;
          }
          else if(mKeyInfo.result == KEY_RESULT_LONG_DOWN)
          {
            mKeyInfo.result = KEY_RESULT_LONG_DOWN_UP;  //长按后松开
          }
					else if( mKeyInfo.result == KEY_RESULT_LONG_DOWN_5S)
					{
						mKeyInfo.result = KEY_RESULT_LONG_DOWN_5S_UP;
					}
					else if( mKeyInfo.result == KEY_RESULT_LONG_LONG_DOWN)
					{
						mKeyInfo.result = KEY_RESULT_LONG_LONG_DOWN_UP;
					}
          else
          {
            mKeyInfo.result = KEY_RESULT_CLICK_UP;
          }

          mKeyInfo.preId = mKeyInfo.key.id; //释放记录上一个按键ID
          mKeyInfo.state = KEY_STATE_IDLE;
        }
      }
      else
      {
        mKeyInfo.state = KEY_STATE_HOLD ;
      }
      break;

    default:
      mKeyInfo.state = KEY_STATE_IDLE;
      break;
  }

  if(KeyCurrentTime > KEY_REPEAT_CLICK_INTERVAL)
  {
    mKeyInfo.repeatCnt = 0;
    KeyCurrentTime = 0;
  }
}


//扫描获取按键值，构造按键输入事件放入环形缓冲区,调用周期为20ms
void KeyGetValuePutEventBuff(void)
{
  KeyInputEvent event = {0};
  static KeyDownResult KeyPreValue = KEY_RESULT_Idle; //记录旧键值

  key_scan();

  switch(mKeyInfo.result)
  {
		case KEY_RESULT_CLICK:
    {
        mKeyInfo.click_time++;
        if(mKeyInfo.click_time > KEY_REPEAT_CLICK_INTERVAL)//防止双击时误触发单击功能
        {
          //TRACE("zsm: KeyGetValuePutEventBuff->KEY_RESULT_CLICK \r\n");
          mKeyInfo.click_time = 0;
          mKeyInfo.result = KEY_RESULT_Idle;
        }
      break;
		}
		case KEY_RESULT_CLICK_UP:
    {
      event.eType = INPUT_EVENT_TYPE_KEY;
			mKeyState.result = KEY_RESULT_CLICK_UP;
      GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
      //放入缓冲区
      if(PutKeyInputEvent(&event))
      {
        TRACE("zsm: PutKeyInputEvent KEY_RESULT_CLICK_UP ERROR \r\n");
      }
      mKeyInfo.result = KEY_RESULT_Idle;
      break;
    }
		case KEY_RESULT_LONG_DOWN:
    {
      if(KeyPreValue != KEY_RESULT_LONG_DOWN) //保证长按只触发一次
      {
        event.eType = INPUT_EVENT_TYPE_KEY;
				mKeyState.result = KEY_RESULT_LONG_DOWN;
        GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
        //放入缓冲区
        if(PutKeyInputEvent(&event))
        {
          TRACE("zsm: PutKeyInputEvent KEY_RESULT_LONG_DOWN ERROR \r\n");
        }
      }
      break;
    }
    case KEY_RESULT_LONG_DOWN_UP:
    {
      event.eType = INPUT_EVENT_TYPE_KEY;
			mKeyState.result = KEY_RESULT_LONG_DOWN_UP;
      GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
      //放入缓冲区
      if(PutKeyInputEvent(&event))
      {
        TRACE("zsm: PutKeyInputEvent KEY_RESULT_LONG_DOWN_UP ERROR \r\n");
      }
      mKeyInfo.result = KEY_RESULT_Idle;
      break;
    }
		case KEY_RESULT_LONG_DOWN_5S:
		{
			if(KeyPreValue != KEY_RESULT_LONG_DOWN_5S) //保证长按只触发一次
			{
				event.eType = INPUT_EVENT_TYPE_KEY;
				mKeyState.result = KEY_RESULT_LONG_DOWN_5S;
				GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
				//放入缓冲区
	      if(PutKeyInputEvent(&event))
	      {
	        TRACE("zsm: PutKeyInputEvent KEY_RESULT_LONG_DOWN ERROR \r\n");
	      }
			}
			break;
		}
		case KEY_RESULT_LONG_DOWN_5S_UP:
		{
			event.eType = INPUT_EVENT_TYPE_KEY;
			mKeyState.result = KEY_RESULT_LONG_DOWN_5S_UP;
			GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
			//放入缓冲区
      if(PutKeyInputEvent(&event))
      {
        TRACE("zsm: PutKeyInputEvent KEY_RESULT_LONG_DOWN_UP ERROR \r\n");
      }
      mKeyInfo.result = KEY_RESULT_Idle;
      break;
		}
    case KEY_RESULT_LONG_LONG_DOWN:
    {
			if(KeyPreValue != KEY_RESULT_LONG_LONG_DOWN) //保证超长按只触发一次
			{
				event.eType = INPUT_EVENT_TYPE_KEY;
				mKeyState.result = KEY_RESULT_LONG_LONG_DOWN;
				GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
	      //放入缓冲区
	      if(PutKeyInputEvent(&event))
	      {
	        TRACE("zsm: PutKeyInputEvent KEY_RESULT_LONG_LONG_DOWN ERROR \r\n");
	      }
			}
      break;
    }
    case KEY_RESULT_LONG_LONG_DOWN_UP:
    {
			event.eType = INPUT_EVENT_TYPE_KEY;
			mKeyState.result = KEY_RESULT_LONG_LONG_DOWN_UP;
			GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
      //放入缓冲区
      if(PutKeyInputEvent(&event))
      {
        TRACE("zsm: PutKeyInputEvent KEY_RESULT_LONG_LONG_DOWN_UP ERROR \r\n");
      }
      mKeyInfo.result = KEY_RESULT_Idle;
      break;
    }
    case KEY_RESULT_REPEAT_CLICK:
    {
      event.eType = INPUT_EVENT_TYPE_KEY;
			mKeyState.result = KEY_RESULT_REPEAT_CLICK;
			GetKeyInfo(mKeyInfo.key.id,&(event.iKey));
      //放入缓冲区
      if(PutKeyInputEvent(&event))
      {
        TRACE("zsm: PutKeyInputEvent KEY_RESULT_REPEAT_CLICK ERROR \r\n");
      }
      mKeyInfo.result = KEY_RESULT_Idle;
      break;
    }
    default:
      break;
  }
  KeyPreValue = mKeyInfo.result;
}

void KeyEventClickHandler(PKeyInputEvent KeyEvent)
{
	PKeyInputEvent KeyEventTemp = KeyEvent;

	switch(KeyEventTemp->iKey.KeyID)
  {
    case KEY_ID_1:
			if(KeyEventTemp->iKey.result == KEY_RESULT_CLICK_UP) //短按松开
			{
				TRACE("zx: KEY_ID_1 KEY_RESULT_CLICK_UP\n");
			}
			else if(KeyEventTemp->iKey.result == KEY_RESULT_LONG_DOWN) //长按1s
			{
				//TRACE("zx: KEY_ID_1 KEY_RESULT_LONG_DOWN\n");
			}
			else if(KeyEventTemp->iKey.result == KEY_RESULT_LONG_DOWN_UP) //长按1s松开
			{
				//TRACE("zx: KEY_ID_1 KEY_RESULT_LONG_DOWN_UP\n");
			}
			else if(KeyEventTemp->iKey.result == KEY_RESULT_LONG_DOWN_5S) //长按5s
			{
				TRACE("zx: KEY_ID_1 KEY_RESULT_LONG_DOWN_5S\n");
				ResetCnt ++;
				if(GetCurrentLightWorkMode() != CDN_FACTORY_MODE)
				  {
		        if(ResetCnt == 1)
		        {
		          SetLedState(CDN_LED_NONE_STATE,0,0);
		          Set_CDN_Light_effect_mode(EFFECT_BREATH, 1);
		        }
		        else if(ResetCnt == 2)
		        {
		          Set_CDN_Light_effect_mode(EFFECT_BREATH, 1);
		        }
		        else if(ResetCnt == 3)
		        {
		          Set_CDN_Light_effect_mode(EFFECT_QUICK_BREATH, 1);
		          sl_btmesh_initiate_node_reset();
		//      SetCurrentLightPowerWorkMode(Power_default_Mode);
		//          KeyEventTemp->iKey.result = KEY_RESULT_LONG_DOWN_5S_UP;
		        }
				  }
				ResetTimerStartFlag = 0;
			}
			else if(KeyEventTemp->iKey.result == KEY_RESULT_LONG_DOWN_5S_UP)
			{
				TRACE("zx: KEY_ID_1 KEY_RESULT_LONG_DOWN_5S_UP\n");
				ResetNextCnt = ResetCnt + 1;
				ResetTimerStartFlag = 1;
			}
			else if(KeyEventTemp->iKey.result == KEY_RESULT_LONG_LONG_DOWN) //超长按
			{
				TRACE("zx: KEY_ID_1 KEY_RESULT_LONG_LONG_DOWN\n");
				ResetCnt = 0;
				ResetNextCnt = 0;
				ResetTimerStartFlag = 0;
			}
			else if(KeyEventTemp->iKey.result == KEY_RESULT_LONG_LONG_DOWN_UP) //超长按松开
			{
				TRACE("zx: KEY_ID_1 KEY_RESULT_LONG_LONG_DOWN_UP\n");
			}
			else if(KeyEventTemp->iKey.result == KEY_RESULT_REPEAT_CLICK)
			{
				TRACE("zx: KEY_ID_1 KEY_RESULT_REPEAT_CLICK\n");
			}
			break;

		default:
			break;
	}
}

//20ms timer handle
void KeyFactoryResetControlHandle(void)
{
	static uint16_t ResetTimerCnt = 0;
	if(ResetTimerStartFlag)
	{
		ResetTimerCnt ++;
		if(ResetTimerCnt >= RESET_TOUCH_INTERVAL)
		{
			if(ResetCnt != ResetNextCnt)
			{
				TRACE("zx: The key is not recognized long down 5s again within 10s\n");
				ResetCnt = 0;
				ResetNextCnt = 0;
			}
			
			ResetTimerStartFlag = 0;
		}
	}
	else
	{
		ResetTimerCnt = 0;
	}
}

void KeyFactoryTestInto(void)
{
#define ENTERFACTORYTESTTIME    50//首次上电进入产测模式判断时间

  static uint8_t  InitialPowerFlag= 0;
  static uint16_t EnterFactoryTestCnt = 0;
  //首次上电&&未入网&&磁铁长时间靠近
  if(!InitialPowerFlag&&!GetProvisionFlag()&&!GPIO_PinInGet(CDN_KEY1_PORT, CDN_KEY1_PIN))
    {
      EnterFactoryTestCnt++;
      if(EnterFactoryTestCnt > ENTERFACTORYTESTTIME)
        {
          SetCurrentLightWorkMode(CDN_FACTORY_MODE);
          SetLedState(CDN_LED_FACTORY_BLINK,0,0);
          mesh_scan_rsp_init();
          TRACE("EnterFactoryTest!!!!\n");
          InitialPowerFlag = 1;
        }
    }
  else
    {
      EnterFactoryTestCnt = 0;
      InitialPowerFlag = 1;
      //TRACE("You'll never be in FactoryTest mode again!!!!\n");
    }
}

